import axios from 'axios'
import './style.css'
import { uuid } from './config'

const doms = {
  createSSEBtn: document.querySelector('.create-sse') as HTMLButtonElement,
  closeSSEBtn: document.querySelector('.close-sse') as HTMLButtonElement,
  startBtn: document.querySelector('.start') as HTMLButtonElement,
  stopBtn: document.querySelector('.stop') as HTMLButtonElement,
  clearBtn: document.querySelector('.clear') as HTMLButtonElement,
  ulContainer: document.querySelector('.ul-container') as HTMLUListElement,
  eventTypeSelect: document.querySelector('.event-type') as HTMLSelectElement,
  eventDataTextarea: document.querySelector('.event-data') as HTMLTextAreaElement,
  sendEventBtn: document.querySelector('.send-event') as HTMLButtonElement,
  sendSSEBtn: document.querySelector('.send-sse') as HTMLButtonElement,
  sendSSEAllBtn: document.querySelector('.send-sse-all') as HTMLButtonElement,
}

type EventSourceConfig = {
  open?: (this: EventSource, ev: MessageEvent) => any
  message?: (this: EventSource, ev: MessageEvent) => any
  error?: (this: EventSource, ev: MessageEvent) => any
  [key: string]: ((this: EventSource, ev: MessageEvent) => any) | undefined
}
class SSE {
  private eventSource: EventSource
  constructor(url: string | URL, options?: EventSourceInit, config?: EventSourceConfig) {
    this.eventSource = new EventSource(url, options)
    if (config) {
      Object.keys(config).forEach((key) => {
        typeof config[key] === 'function' && this.addEventListener(key, config[key])
      })
    }
  }
  addEventListener(
    event: string,
    listener: (this: EventSource, e: MessageEvent) => any,
    options?: boolean | AddEventListenerOptions,
  ) {
    this.eventSource.addEventListener(event, listener, options)
  }
  removeEventListener(
    event: string,
    listener: (this: EventSource, e: MessageEvent) => any,
    options?: boolean | AddEventListenerOptions,
  ) {
    this.eventSource.removeEventListener(event, listener, options)
  }
  dispatchEvent(event: string, data: any) {
    this.eventSource.dispatchEvent(new CustomEvent(event, { detail: data }))
  }
  close() {
    this.eventSource.close()
  }
}

let sse: SSE | null = null
doms.createSSEBtn.addEventListener('click', () => {
  if (sse) return
  sse = new SSE(
    `/api/sse?uuid=${uuid}`,
    {
      withCredentials: true,
    },
    {
      open: (e) => {
        console.log('open', e)
      },
      message: (e: Event) => {
        console.log('message', e)
        if (e instanceof MessageEvent) {
          const li = document.createElement('li')
          li.textContent = e.data
          doms.ulContainer.appendChild(li)
        } else if (e instanceof CustomEvent) {
          const li = document.createElement('li')
          li.textContent = JSON.stringify(e.detail)
          doms.ulContainer.appendChild(li)
        }
        doms.ulContainer.lastElementChild?.scrollIntoView()
      },
      error: (e) => {
        console.log('error', e)
      },
      custom: (e: Event) => {
        console.log('custom', e)
        if (e instanceof MessageEvent) {
          const li = document.createElement('li')
          li.textContent = e.data
          doms.ulContainer.appendChild(li)
        } else if (e instanceof CustomEvent) {
          const li = document.createElement('li')
          li.textContent = JSON.stringify(e.detail)
          doms.ulContainer.appendChild(li)
        }
        doms.ulContainer.lastElementChild?.scrollIntoView()
      },
      'server-time': (e: Event) => {
        console.log('server-time', e)
        if (e instanceof MessageEvent) {
          const li = document.createElement('li')
          li.textContent = e.data
          doms.ulContainer.appendChild(li)
        } else if (e instanceof CustomEvent) {
          const li = document.createElement('li')
          li.textContent = JSON.stringify(e.detail)
          doms.ulContainer.appendChild(li)
        }
        doms.ulContainer.lastElementChild?.scrollIntoView()
      },
    },
  )
})
doms.closeSSEBtn.addEventListener('click', () => {
  if (!sse) return
  sse.dispatchEvent('message', {
    message: 'close',
  })
  sse.close()
  sse = null
})
doms.startBtn.addEventListener('click', () => {
  if (!sse) return
  axios.post('/api/startReportCurrentTime', {
    uuid,
  })
})
doms.stopBtn.addEventListener('click', () => {
  if (!sse) return
  axios.post('/api/stopReportCurrentTime', {
    uuid,
  })
})
doms.clearBtn.addEventListener('click', () => {
  doms.ulContainer.innerHTML = ''
})
doms.sendEventBtn.addEventListener('click', () => {
  if (!sse) return
  const eventType = doms.eventTypeSelect.value
  const eventData = doms.eventDataTextarea.value
  sse.dispatchEvent(eventType, JSON.parse(eventData) || '')
})
doms.sendSSEBtn.addEventListener('click', () => {
  if (!sse) return
  const eventType = doms.eventTypeSelect.value
  const eventData = doms.eventDataTextarea.value
  axios.post('/api/reportCustomEvent', {
    uuid,
    type: eventType,
    data: JSON.stringify(JSON.parse(eventData) || ''),
  })
})
doms.sendSSEAllBtn.addEventListener('click', () => {
  if (!sse) return
  const eventType = doms.eventTypeSelect.value
  const eventData = doms.eventDataTextarea.value
  axios.post('/api/reportAllClient', {
    uuid,
    type: eventType,
    data: JSON.stringify(JSON.parse(eventData) || ''),
  })
})
